<template>
  <van-popup v-model:show="show" position="right" :style="{ width: '100%', height: '100%' }">
    <!-- 点击左箭头关闭弹层 -->
    <cp-nav-bar :back="() => { show = false }" :title="showTitle" right-text="保存 " @click-right="save"></cp-nav-bar>
    <van-form ref="formRef" autocomplete="off" style="margin-top: 46px;">
      <van-field :rules="ruleName" name="name" v-model="patient.name" label="真实姓名" placeholder="请输入真实姓名">
      </van-field>
      <van-field :rules="ruleIdCard" name="idCard" v-model="patient.idCard" label="身份证号" placeholder="请输入身份证号" />
      <van-field label="性别">
        <!-- 单选按钮组件 -->
        <template #input>
          <cp-radio-btn :options="options" v-model="patient.gender">
          </cp-radio-btn>
        </template>
      </van-field>
      <van-field label="默认就诊人">
        <template #input>
          <van-checkbox round v-model="defaultFlag" checked-color="#16C2A3" />
        </template>
      </van-field>
    </van-form>
    <!-- 动作栏组件 -->
    <van-action-bar v-if="patient.id">
      <van-action-bar-button @click="del">删除</van-action-bar-button>
    </van-action-bar>
  </van-popup>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import type { Patient } from '@/types/user'
import { success, error } from '@/utils/tools'
import { type FormInstance, showConfirmDialog } from 'vant'
import 'vant/es/dialog/style'

import IDValidator from 'id-validator'
import { addPatient, editPatient, patienDetail, delPatient } from '@/services/user'
// 控制弹出层的显示和隐藏
const show = ref(false)
// 打开弹出层
async function open(id: string) {
  if (id) {
    // 编辑操作
    // 根据传入的id获取患者数据，给表单数据赋值
    await getPatientDetail(id)
  }
  show.value = true
}
// 标题
const showTitle = computed(() => patient.value.id ? '编辑患者' : '添加患者')
// 获取患者详情
async function getPatientDetail(id: string) {
  const { data } = await patienDetail(id)
  patient.value = {
    name: data.name,
    idCard: data.idCard,
    gender: data.gender,
    defaultFlag: data.defaultFlag,
    id: data.id
  }
}

// 关闭弹出层
function close() {
  // 重置表单数据
  patient.value = {
    name: '',
    idCard: '',
    gender: 0,
    defaultFlag: 1
  }
}

// 男女选择的单选框组件选项
const options = [
  { label: '男', value: 1 },
  { label: '女', value: 0 }
]

// 表单选项数据
const patient = ref<Patient>({
  name: '',
  idCard: '',
  gender: 0,
  defaultFlag: 1
})

// 复选框组件的选项是布尔类型的true和false,而我们传递的表单数据是1和0,true和fals依赖我们的0和1
const defaultFlag = computed({
  get() {
    return patient.value.defaultFlag === 1
  },
  set(newVal) {
    patient.value.defaultFlag = newVal ? 1 : 0
  }
})

const formRef = ref<FormInstance | null>(null)
// 真实姓名的验证规则
const ruleName = [
  { required: true, message: '真实姓名必填' },
  { pattern: /^[\u4e00-\u9fa5]{2,10}$/, message: '姓名必须是2-10个汉字' }
]
// 身份证的验证规则
const ruleIdCard = [
  { required: true, message: '身份证必填' },
  { validator: checkIdCard, message: '身份证非法' }
]
// 获取验证身份证的对象
const Validator = new IDValidator()
// 验证身份证是否合法的验证函数
function checkIdCard(value: string) {
  return Validator.isValid(value)
}

const emit = defineEmits<{
  (e: 'get-new-patient'): void
}>()

// 提交表单数据
async function save() {
  // 数据验证
  // 验证真实姓名
  await formRef.value?.validate('name')
  // 验证身份证
  await formRef.value?.validate('idCard')
  // 从里面获取性别
  const { sex } = Validator.getInfo(patient.value.idCard)
  if (patient.value.gender !== sex) return error('性别和身份证不符')
  // 添加/修改
  patient.value.id ? await editPatient(patient.value) : await addPatient(patient.value)
  // 成功的提示信息
  success('操作成功')
  // 关闭弹层
  show.value = false
  // 获取最新的患者数据
  emit('get-new-patient')
}

// 删除患者
async function del() {
  if (patient.value.id) {
    await showConfirmDialog({
      title: '温馨提示',
      message: `您确认要删除 ${patient.value.name} 患者信息吗 ？`,
      cancelButtonText: '取消',
      confirmButtonText: '确认'
    })
    await delPatient(patient.value.id)
    success('删除患者成功')
    show.value = false
    emit('get-new-patient')
  }

}


defineExpose({ open, close })
</script>

<style scoped lang="scss">
// 底部操作栏
.van-action-bar {
  padding: 0 10px;
  margin-bottom: 10px;

  .van-button {
    color: var(--cp-price);
    background-color: var(--cp-bg);
  }
}
</style>